<?php

CCore::Using('base.collection');

class CCoreLabsWebMailFolder
{
	const OBJECT_ERROR_CODE = 1600;

	/**
	 * @var string
	 */
	public $FullName;

	/**
	 * @var string
	 */
	public $Name;

	/**
	 * @var int
	 */
	public $Count;

	/**
	 * @var int
	 */
	public $Unread;

	/**
	 * @var bool
	 */
	public $Flags;
	
	/**
	 * @var bool
	 */
	public $NoSelect;

	/**
	 * @var int
	 */
	public $Type;

	/**
	 * @var CCoreLabsWebMailFolderCollection
	 */
	public $SubFolders;

	/**
	 * @return CCoreLabsWebMailFolder
	 */
	public function __construct()
	{
		$this->FullName = '';
		$this->Name = '';
		$this->Count = 0;
		$this->Unread = 0;
		$this->Flags = array();
		$this->NoSelect = true;
		$this->Delimiter = '/';
		$this->Type = C_WEBMAIL_FOLDER_TYPE_USER;
		$this->SubFolders = new CCoreLabsWebMailFolderCollection();
	}

	/**
	 * @param CCoreNetImapFolder $oImapFolder
	 * @return void
	 */
	public function InitByImapFolder(CCoreNetImapFolder $oImapFolder)
	{
		$this->FullName = $oImapFolder->FullName;
		$this->Name = CCoreBaseUtils::Utf7ModifiedToUtf8(
			array_pop(explode($oImapFolder->Delimiter, $oImapFolder->FullName)));
		$this->Flags = $oImapFolder->Flags;
		$this->Delimiter = $oImapFolder->Delimiter;
		$this->NoSelect = in_array('\noselect', $oImapFolder->Flags);
		$this->_initFolderType();
	}

	/**
	 * @return void
	 */
	public function InitAsPop3InboxFolder()
	{
		$this->FullName = 'INBOX';
		$this->Name = 'INBOX';
		$this->NoSelect = false;
		$this->Type = C_WEBMAIL_FOLDER_TYPE_INBOX;
	}

	/**
	 * @return void
	 */
	private function _initFolderType()
	{
		switch (true)
		{
			case ('INBOX' === strtoupper($this->FullName)):
				$this->Type = C_WEBMAIL_FOLDER_TYPE_INBOX;
				break;
			case (in_array('\inbox', $this->Flags)):
				$this->Type = C_WEBMAIL_FOLDER_TYPE_INBOX;
				break;
			case (in_array('\drafts', $this->Flags)):
				$this->Type = C_WEBMAIL_FOLDER_TYPE_DRAFTS;
				break;
			case (in_array('\sent', $this->Flags)):
				$this->Type = C_WEBMAIL_FOLDER_TYPE_SENT;
				break;
			case (in_array('\spam', $this->Flags)):
				$this->Type = C_WEBMAIL_FOLDER_TYPE_SPAM;
				break;
			case (in_array('\trash', $this->Flags)):
				$this->Type = C_WEBMAIL_FOLDER_TYPE_TRASH;
				break;
		}
	}
}

class CCoreLabsWebMailFolderCollection extends ACoreBaseCollection
{
	const OBJECT_ERROR_CODE = 1700;

	/**
	 * @return CCoreLabsWebMailFolderCollection
	 */
	public function __construct()
	{
		parent::__construct();
	}
	
	/**
	 * @param CCoreLabsWebMailFolder $oWebMailFolder
	 * @return void
	 */
	public function Add(CCoreLabsWebMailFolder $oWebMailFolder)
	{
		CCore::CheckTypes(array('$oWebMailFolder'));

		parent::Add($oWebMailFolder);
	}

	/**
	 * @return array
	 */
	public function &GetFolderListFromTreeAsArray()
	{
		$oFolderList = new CCoreLabsWebMailFolderCollection();
		$this->_createFolderListFromTree($oFolderList);
		return $oFolderList->GetAsArray();
	}

	/**
	 * @return CCoreLabsWebMailFolderCollection
	 */
	public function &GetFolderListFromTree()
	{
		$oFolderList = new CCoreLabsWebMailFolderCollection();
		$this->_createFolderListFromTree($oFolderList);
		return $oFolderList;
	}

	/**
	 * @param CCoreLabsWebMailFolderCollection $oFolderList
	 */
	private function _createFolderListFromTree(CCoreLabsWebMailFolderCollection &$oFolderList)
	{
		for ($iIndex = 0, $iCount = $this->Count(); $iIndex < $iCount; $iIndex++)
		{
			$oFolder =& $this->GetByIndex($iIndex);
			$oFolderList->Add($oFolder);
			if (null !== $oFolder->SubFolders && 0 < $oFolder->SubFolders->Count())
			{
				$oFolder->SubFolders->_createFolderListFromTree($oFolderList);
			}
			unset($oFolder);
		}
	}

	/**
	 * @param array $aUnsortedWebMailFolders
	 * @return void
	 */
	public function InitByUnsortedFolderArray($aUnsortedWebMailFolders)
	{
		$this->Clear();

		$aSortedByLenImapFolders = array();
		foreach ($aUnsortedWebMailFolders as /* @var $oWebMailFolder CCoreLabsWebMailFolder */ &$oWebMailFolder)
		{
			$aSortedByLenImapFolders[$oWebMailFolder->FullName] =& $oWebMailFolder;
			unset($oWebMailFolder);
		}
		unset($aUnsortedWebMailFolders);

		// Создание несуществующих узлов папок для полного дерева папок
		$aAddedFolders = array();
		foreach ($aSortedByLenImapFolders as /* @var $oWebMailFolder CCoreLabsWebMailFolder */ &$oWebMailFolder)
		{
			$aFolderExplode = explode($oWebMailFolder->Delimiter, $oWebMailFolder->FullName);
			if (1 < count($aFolderExplode))
			{
				array_pop($aFolderExplode);
				
				$sName = '';
				foreach ($aFolderExplode as $sFolderExplodeItem)
				{
					$sName .= (0 < strlen($sName))
						? $oWebMailFolder->Delimiter.$sFolderExplodeItem : $sFolderExplodeItem;

					if (!isset($aSortedByLenImapFolders[$sName]))
					{
						$oFolderToAdd = new CCoreLabsWebMailFolder();
						$oFolderToAdd->FullName = $sName;
						$oFolderToAdd->Name = CCoreBaseUtils::Utf7ModifiedToUtf8(
							array_pop(explode($oWebMailFolder->Delimiter, $sName)));
						$oFolderToAdd->Flags = array('/noselect');
						$oFolderToAdd->NoSelect = true;
						$oFolderToAdd->Delimiter = $oWebMailFolder->Delimiter;
						$aAddedFolders[$sName] = $oFolderToAdd;
						unset($oFolderToAdd);
					}
				}
			}
			unset($oWebMailFolder);
		}

		$aSortedByLenImapFolders = array_merge($aSortedByLenImapFolders, $aAddedFolders);

		ksort($aSortedByLenImapFolders);

		foreach ($aSortedByLenImapFolders as /* @var $oWebMailFolder CCoreLabsWebMailFolder */ &$oWebMailFolder)
		{
			$this->AddWithPositionSearch($oWebMailFolder);
			unset($oWebMailFolder);
		}
		unset($aSortedByLenImapFolders);
	}

	/**
	 * @param CCoreLabsWebMailFolder $oWebMailFolder
	 * @return bool
	 */
	public function AddWithPositionSearch(CCoreLabsWebMailFolder $oWebMailFolder)
	{
		CCore::CheckTypes(array('$oWebMailFolder'));

		$bIsAdded = false;
		$aList =& $this->GetAsArray();
		foreach ($aList as /* @var $oItemFolder CCoreLabsWebMailFolder */ $oItemFolder)
		{
			if (0 === strpos($oWebMailFolder->FullName, $oItemFolder->FullName))
			{
				if ($oItemFolder->SubFolders->AddWithPositionSearch($oWebMailFolder))
				{
					$bIsAdded = true;
				}
				break;
			}
		}

		if (!$bIsAdded)
		{
			$bIsAdded = true;
			$this->Add($oWebMailFolder);
		}

		return $bIsAdded;
	}
}
